package cn.com.anypay.manager.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 微信API调用监控服务
 * 负责记录和统计微信API调用的性能指标和错误信息
 */
@Slf4j
@Service
public class WeChatApiMonitorService {
    
    /**
     * API调用统计信息
     */
    private final ConcurrentHashMap<String, ApiCallStats> apiCallStats = new ConcurrentHashMap<>();
    
    /**
     * 记录API调用开始
     * 
     * @param apiName API名称
     * @param requestId 请求ID
     * @return 调用记录ID
     */
    public String recordApiCallStart(String apiName, String requestId) {
        String callId = generateCallId(apiName, requestId);
        
        log.info("微信API调用开始: {} - 请求ID: {}, 调用ID: {}", apiName, requestId, callId);
        
        // 更新统计信息
        ApiCallStats stats = apiCallStats.computeIfAbsent(apiName, k -> new ApiCallStats());
        stats.incrementTotalCalls();
        
        return callId;
    }
    
    /**
     * 记录API调用成功
     * 
     * @param callId 调用记录ID
     * @param apiName API名称
     * @param duration 调用耗时（毫秒）
     * @param responseSize 响应大小（字节）
     */
    public void recordApiCallSuccess(String callId, String apiName, long duration, long responseSize) {
        log.info("微信API调用成功: {} - 调用ID: {}, 耗时: {}ms, 响应大小: {}字节", 
                apiName, callId, duration, responseSize);
        
        // 更新统计信息
        ApiCallStats stats = apiCallStats.get(apiName);
        if (stats != null) {
            stats.incrementSuccessCalls();
            stats.updateAverageResponseTime(duration);
            stats.updateLastSuccessTime();
        }
        
        // 记录性能指标
        if (duration > 5000) { // 超过5秒的慢请求
            log.warn("微信API调用响应较慢: {} - 耗时: {}ms", apiName, duration);
        }
    }
    
    /**
     * 记录API调用失败
     * 
     * @param callId 调用记录ID
     * @param apiName API名称
     * @param duration 调用耗时（毫秒）
     * @param errorCode 错误码
     * @param errorMessage 错误信息
     */
    public void recordApiCallFailure(String callId, String apiName, long duration, 
                                   String errorCode, String errorMessage) {
        log.error("微信API调用失败: {} - 调用ID: {}, 耗时: {}ms, 错误码: {}, 错误信息: {}", 
                apiName, callId, duration, errorCode, errorMessage);
        
        // 更新统计信息
        ApiCallStats stats = apiCallStats.get(apiName);
        if (stats != null) {
            stats.incrementFailureCalls();
            stats.recordError(errorCode, errorMessage);
            stats.updateLastFailureTime();
        }
        
        // 记录错误统计
        recordErrorStatistics(apiName, errorCode, errorMessage);
    }
    
    /**
     * 记录API调用重试
     * 
     * @param callId 调用记录ID
     * @param apiName API名称
     * @param retryCount 重试次数
     * @param reason 重试原因
     */
    public void recordApiCallRetry(String callId, String apiName, int retryCount, String reason) {
        log.warn("微信API调用重试: {} - 调用ID: {}, 重试次数: {}, 重试原因: {}", 
                apiName, callId, retryCount, reason);
        
        // 更新统计信息
        ApiCallStats stats = apiCallStats.get(apiName);
        if (stats != null) {
            stats.incrementRetryCalls();
        }
    }
    
    /**
     * 获取API调用统计信息
     * 
     * @param apiName API名称
     * @return 统计信息
     */
    public ApiCallStats getApiCallStats(String apiName) {
        return apiCallStats.get(apiName);
    }
    
    /**
     * 获取所有API调用统计信息
     * 
     * @return 所有统计信息
     */
    public ConcurrentHashMap<String, ApiCallStats> getAllApiCallStats() {
        return new ConcurrentHashMap<>(apiCallStats);
    }
    
    /**
     * 重置API调用统计信息
     * 
     * @param apiName API名称
     */
    public void resetApiCallStats(String apiName) {
        apiCallStats.remove(apiName);
        log.info("已重置微信API调用统计信息: {}", apiName);
    }
    
    /**
     * 重置所有API调用统计信息
     */
    public void resetAllApiCallStats() {
        apiCallStats.clear();
        log.info("已重置所有微信API调用统计信息");
    }
    
    /**
     * 生成调用记录ID
     * 
     * @param apiName API名称
     * @param requestId 请求ID
     * @return 调用记录ID
     */
    private String generateCallId(String apiName, String requestId) {
        return String.format("%s_%s_%d", apiName, requestId, System.currentTimeMillis());
    }
    
    /**
     * 记录错误统计
     * 
     * @param apiName API名称
     * @param errorCode 错误码
     * @param errorMessage 错误信息
     */
    private void recordErrorStatistics(String apiName, String errorCode, String errorMessage) {
        // 这里可以实现更详细的错误统计逻辑
        // 比如记录到数据库、发送告警等
        
        if ("40001".equals(errorCode) || "40030".equals(errorCode)) {
            log.warn("微信API令牌相关错误频发: {} - 错误码: {}", apiName, errorCode);
        } else if ("45011".equals(errorCode)) {
            log.error("微信API调用频率超限: {} - 需要实施限流措施", apiName);
        } else if (errorCode != null && errorCode.startsWith("5")) {
            log.error("微信API服务器错误: {} - 错误码: {}, 可能需要联系微信技术支持", apiName, errorCode);
        }
    }
    
    /**
     * API调用统计信息类
     */
    public static class ApiCallStats {
        private final AtomicLong totalCalls = new AtomicLong(0);
        private final AtomicLong successCalls = new AtomicLong(0);
        private final AtomicLong failureCalls = new AtomicLong(0);
        private final AtomicLong retryCalls = new AtomicLong(0);
        private volatile long totalResponseTime = 0;
        private volatile LocalDateTime lastSuccessTime;
        private volatile LocalDateTime lastFailureTime;
        private final ConcurrentHashMap<String, AtomicLong> errorCounts = new ConcurrentHashMap<>();
        
        public void incrementTotalCalls() {
            totalCalls.incrementAndGet();
        }
        
        public void incrementSuccessCalls() {
            successCalls.incrementAndGet();
        }
        
        public void incrementFailureCalls() {
            failureCalls.incrementAndGet();
        }
        
        public void incrementRetryCalls() {
            retryCalls.incrementAndGet();
        }
        
        public void updateAverageResponseTime(long responseTime) {
            synchronized (this) {
                totalResponseTime += responseTime;
            }
        }
        
        public void updateLastSuccessTime() {
            lastSuccessTime = LocalDateTime.now();
        }
        
        public void updateLastFailureTime() {
            lastFailureTime = LocalDateTime.now();
        }
        
        public void recordError(String errorCode, String errorMessage) {
            if (errorCode != null) {
                errorCounts.computeIfAbsent(errorCode, k -> new AtomicLong(0)).incrementAndGet();
            }
        }
        
        // Getters
        public long getTotalCalls() {
            return totalCalls.get();
        }
        
        public long getSuccessCalls() {
            return successCalls.get();
        }
        
        public long getFailureCalls() {
            return failureCalls.get();
        }
        
        public long getRetryCalls() {
            return retryCalls.get();
        }
        
        public double getSuccessRate() {
            long total = totalCalls.get();
            return total > 0 ? (double) successCalls.get() / total * 100 : 0.0;
        }
        
        public double getAverageResponseTime() {
            long success = successCalls.get();
            return success > 0 ? (double) totalResponseTime / success : 0.0;
        }
        
        public LocalDateTime getLastSuccessTime() {
            return lastSuccessTime;
        }
        
        public LocalDateTime getLastFailureTime() {
            return lastFailureTime;
        }
        
        public ConcurrentHashMap<String, AtomicLong> getErrorCounts() {
            return new ConcurrentHashMap<>(errorCounts);
        }
        
        @Override
        public String toString() {
            return String.format("ApiCallStats{总调用=%d, 成功=%d, 失败=%d, 重试=%d, 成功率=%.2f%%, 平均响应时间=%.2fms}", 
                    getTotalCalls(), getSuccessCalls(), getFailureCalls(), getRetryCalls(), 
                    getSuccessRate(), getAverageResponseTime());
        }
    }
}